using System;
using NUnit.Framework;
using UnityEngine;

namespace JH
{
    /// <summary>
    /// 缓动函数测试类: 数值插值
    /// </summary>
    public class TestEaseFunctionNumeric
    {
        /// <summary>
        /// 浮点数比较的容差值
        /// </summary>
        private const float Epsilon = 0.0001f;

        #region 基础数值类型测试

        /// <summary>
        /// 测试基础数值类型的线性插值
        /// </summary>
        [Test]
        public void TestBasicNumberTypes()
        {
            // 测试 float
            float floatResult = EaseFunctionNumeric.Tween(0f, 100f, Ease.Linear, 0.5f);
            Assert.AreEqual(50f, floatResult, Epsilon, "float线性插值测试失败");

            // 测试 int
            int intResult = EaseFunctionNumeric.Tween(0, 100, Ease.Linear, 0.5f);
            Assert.AreEqual(50, intResult, "int线性插值测试失败");

            // 测试 double
            double doubleResult = EaseFunctionNumeric.Tween(0.0, 100.0, Ease.Linear, 0.5f);
            Assert.AreEqual(50.0, doubleResult, Epsilon, "double线性插值测试失败");

            // 测试 decimal
            decimal decimalResult = EaseFunctionNumeric.Tween(0m, 100m, Ease.Linear, 0.5f);
            Assert.AreEqual(50m, decimalResult, "decimal线性插值测试失败");
        }

        #endregion

        #region Vector类型测试

        /// <summary>
        /// 测试Vector2/3/4类型
        /// </summary>
        [Test]
        public void TestVectorTypes()
        {
            // 测试 Vector2
            Vector2 v2Result = EaseFunctionNumeric.Tween(
                Vector2.zero,
                Vector2.one,
                Ease.Linear,
                0.5f
            );
            Assert.AreEqual(new Vector2(0.5f, 0.5f), v2Result, "Vector2线性插值测试失败");

            // 测试 Vector3
            Vector3 v3Result = EaseFunctionNumeric.Tween(
                Vector3.zero,
                Vector3.one,
                Ease.Linear,
                0.5f
            );
            Assert.AreEqual(new Vector3(0.5f, 0.5f, 0.5f), v3Result, "Vector3线性插值测试失败");

            // 测试 Vector4
            Vector4 v4Result = EaseFunctionNumeric.Tween(
                Vector4.zero,
                new Vector4(1, 1, 1, 1),
                Ease.Linear,
                0.5f
            );
            Assert.AreEqual(new Vector4(0.5f, 0.5f, 0.5f, 0.5f), v4Result, "Vector4线性插值测试失败");
        }

        #endregion

        #region Color类型测试

        /// <summary>
        /// 测试Color类型
        /// </summary>
        [Test]
        public void TestColorType()
        {
            // 测试从白色到黑色的过渡
            Color result = EaseFunctionNumeric.Tween(
                Color.white,
                Color.black,
                Ease.Linear,
                0.5f
            );
            Assert.AreEqual(new Color(0.5f, 0.5f, 0.5f, 1f), result, "Color线性插值测试失败");

            // 测试带透明度的颜色
            Color result2 = EaseFunctionNumeric.Tween(
                new Color(1, 1, 1, 1),
                new Color(0, 0, 0, 0),
                Ease.Linear,
                0.5f
            );
            Assert.AreEqual(new Color(0.5f, 0.5f, 0.5f, 0.5f), result2, "Color带透明度插值测试失败");
        }

        #endregion

        #region 边界值测试

        /// <summary>
        /// 测试边界值情况
        /// </summary>
        [Test]
        public void TestBoundaryValues()
        {
            // 测试起始点 (f = 0)
            float startResult = EaseFunctionNumeric.Tween(0f, 100f, Ease.Linear, 0f);
            Assert.AreEqual(0f, startResult, Epsilon, "起始点测试失败");

            // 测试终点 (f = 1)
            float endResult = EaseFunctionNumeric.Tween(0f, 100f, Ease.Linear, 1f);
            Assert.AreEqual(100f, endResult, Epsilon, "终点测试失败");

            // 测试中点精确度 (f = 0.5)
            float midResult = EaseFunctionNumeric.Tween(0f, 100f, Ease.Linear, 0.5f);
            Assert.AreEqual(50f, midResult, Epsilon, "中点测试失败");
        }

        #endregion

        #region 特殊缓动类型测试

        /// <summary>
        /// 测试各种特殊的缓动类型
        /// </summary>
        [Test]
        public void TestSpecialEaseTypes()
        {
            // 测试弹性缓动
            float elasticResult = EaseFunctionNumeric.Tween(0f, 100f, Ease.OutElastic, 0.5f);
            Assert.That(elasticResult, Is.Not.EqualTo(50f), "弹性缓动测试失败");

            // 测试回弹缓动
            float bounceResult = EaseFunctionNumeric.Tween(0f, 100f, Ease.OutBounce, 0.5f);
            Assert.That(bounceResult, Is.Not.EqualTo(50f), "回弹缓动测试失败");

            // 测试回退缓动
            float backResult = EaseFunctionNumeric.Tween(0f, 100f, Ease.OutBack, 0.5f);
            Assert.That(backResult, Is.GreaterThan(50f), "回退缓动测试失败");
        }

        #endregion

        #region 异常测试

        /// <summary>
        /// 测试不支持的类型是否会抛出异常
        /// </summary>
        [Test]
        public void TestUnsupportedTypes()
        {
            // 测试自定义结构体是否会抛出异常
            Assert.Throws<NotSupportedException>(() =>
            {
                var start = new CustomStruct { Value = 0 };
                var end = new CustomStruct { Value = 100 };
                EaseFunctionNumeric.Tween(start, end, Ease.Linear, 0.5f);
            }, "未能正确处理不支持的类型");
        }

        /// <summary>
        /// 用于测试的自定义结构体
        /// </summary>
        private struct CustomStruct
        {
            public int Value;
        }

        #endregion
    }
}